#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <math.h>

#include "ohos_types.h"
#include "iot_errno.h"
#include "iot_gpio.h"
#include "iot_i2c.h"
#include "iot_gpio_ex.h"

#include "sht3x.h"

static uint8_t SHT3xCheckCrc(uint8_t data[], uint8_t nbrOfBytes, uint8_t checksum)
{
    uint8_t crc = 0xFF;
    uint8_t bit = 0;
    uint8_t byteCtr ;
    const int16_t POLYNOMIAL = 0x131;
    //calculates 8-Bit checksum with given polynomial
    for(byteCtr = 0; byteCtr < nbrOfBytes; ++byteCtr)
    {
        crc ^= (data[byteCtr]);
        for ( bit = 8; bit > 0; --bit)
        {
            if (crc & 0x80) crc = (crc << 1) ^ POLYNOMIAL;
            else crc = (crc << 1);
        }
    }
	
    if(crc != checksum)
		return 1;
    else
		return 0;
	
}

static float SHT3xCalcTemperatureC(uint16_t u16sT)
{
    float temperatureC = 0;            // variable for result

    u16sT &= ~0x0003;           // clear bits [1..0] (status bits)
    //-- calculate temperature [℃] --
    temperatureC = (175 * (float)u16sT / 65535 - 45); //T = -45 + 175 * rawValue / (2^16-1)
	
    return temperatureC;
}

static float SHT3xCalcRH(uint16_t u16sRH)
{
    float humidityRH = 0;              // variable for result
	
    u16sRH &= ~0x0003;          // clear bits [1..0] (status bits)
    //-- calculate relative humidity [%RH] --
    humidityRH = (100 * (float)u16sRH / 65535);  // RH = rawValue / (2^16-1) * 10

    return humidityRH;
}

/***************************************************************
* 函数名称: SHT3XReset
* 说    明: SHT30复位
* 参    数: 无
* 返 回 值: 无
***************************************************************/
void SHT3XReset(void)
{
    const uint8_t send_data[2] = { 0x30,0xA2 };
    IoTI2cWrite(SHT3X_I2C_IDX, (SHT3X_I2C_ADDR<<1)|0x00, send_data, 2); 
}

/***************************************************************
* 函数名称: SHT3XInit
* 说    明: 初始化SHT3X (SHT30)，设置测量周期
* 参    数: 无
* 返 回 值: 无
***************************************************************/
void SHT3XInit(void)
{
    const uint8_t send_data[2] = { 0x22,0x36 };
    IoTI2cWrite(SHT3X_I2C_IDX, (SHT3X_I2C_ADDR<<1)|0x00, send_data, 2); 
}

/***************************************************************
* 函数名称: SHT3XReadData
* 说    明: 测量温度、湿度
* 参    数: 无
* 返 回 值: 无
***************************************************************/
void SHT3XReadData(float *temperature, float *humidity)
{
    uint8_t  data[3];    //data array for checksum verification
    uint16_t dat,tmp;
    uint8_t SHT3X_Data_Buffer[6]; //byte 0,1 is temperature byte 4,5 is humidity
    const uint8_t send_data[2] = { 0xE0,0x00};

    IoTI2cWrite(SHT3X_I2C_IDX, (SHT3X_I2C_ADDR<<1)|0x00, send_data, 2);
    IoTI2cRead(SHT3X_I2C_IDX, (SHT3X_I2C_ADDR<<1) | 0x00, SHT3X_Data_Buffer, 6);//Read sensor data

    //    /* check tem */
    data[0] = SHT3X_Data_Buffer[0];
    data[1] = SHT3X_Data_Buffer[1];
    data[2] = SHT3X_Data_Buffer[2];

    tmp = SHT3xCheckCrc(data, 2, data[2]);
    if( !tmp ) /* value is ture */
    {
        dat = ((uint16_t)data[0] << 8) | data[1];
        if (temperature != NULL)
            *temperature = SHT3xCalcTemperatureC( dat );
    }

    //    /* check humidity */
    data[0] = SHT3X_Data_Buffer[3];
    data[1] = SHT3X_Data_Buffer[4];
    data[2] = SHT3X_Data_Buffer[5];

    tmp = SHT3xCheckCrc(data, 2, data[2]);
    if( !tmp ) /* value is ture */
    {
        dat = ((uint16_t)data[0] << 8) | data[1];
        if (humidity != NULL)
            *humidity = SHT3xCalcRH( dat );
    }
}


